const pool = {
  singleFlight: {},
};
const LockUtil = {
  /**
   * 将并发调用合并成一个单独的调用
   * @param {*} key 锁名
   * @param {Function?} fn 要调用的函数,不传入此参数将成为一个读锁
   * @returns {Promise<*>}
   */
  async singleFlight({ key, fn }) {
    let lockObj = pool.singleFlight[key];

    if (!fn) {
      return lockObj?.lock;
    }

    if (!lockObj) {
      lockObj = {
        lock: null,
        resolve: null,
        reject: null,
      };
      pool.singleFlight[key] = lockObj;
    }
    if (lockObj.lock) {
      return lockObj.lock;
    }
    lockObj.lock = new Promise((resolve, reject) => {
      lockObj.resolve = resolve;
      lockObj.reject = reject;
    });
    try {
      const res = await fn();
      lockObj.resolve(res);
      return res;
    } catch (e) {
      lockObj.reject(e);
      throw e;
    } finally {
      delete lockObj.lock;
      delete lockObj.resolve;
      delete lockObj.reject;
      delete pool.singleFlight[key];
    }
  },
};

export default LockUtil;
